package com.xand.bt.terminal.market;

import java.util.HashMap;
import java.util.Map;

import com.xand.bt.terminal.common.api.MarketDepthUpdate;
import com.xand.bt.terminal.common.util.NumberHelper;
import com.xand.bt.terminal.ui.depth.MarketDepthLevel;
import com.xand.bt.terminal.ui.depth.MarketDepthTableController;
import com.xand.bt.terminal.util.BitcoinTerminalConst;

public class MarketStore {

	private Map<String, ConnectorMarketStore> connectorMarketStores;
	
	private Map<String, MarketDepthTableController> marketDepthTableControllerHashedByConnector;
	
	public MarketStore() {
		this.connectorMarketStores = new HashMap<String, ConnectorMarketStore>();
		this.marketDepthTableControllerHashedByConnector = new HashMap<String, MarketDepthTableController>();
	}
	
	public void addMarketDepthTableController(String connectorClassName, MarketDepthTableController controller) {
		this.marketDepthTableControllerHashedByConnector.put(connectorClassName, controller);
	}
	
	public void createConnectorMarketStore(String connectorClass) {
		ConnectorMarketStore connectorMarketStore = new ConnectorMarketStore(connectorClass);
		
		this.connectorMarketStores.put(connectorClass, connectorMarketStore);
	}
	
	public ConnectorMarketStore getConnectorMarketStore(String connectorClass) {
		return this.connectorMarketStores.get(connectorClass);
	}
	
	public void processMarketDepthUpdate(String connectorClassName, 
			MarketDepthUpdate marketDepthUpdate) {
		
		int direction;
		if(marketDepthUpdate.getDirection() == MarketDepthUpdate.DIRECTION_ASK) {
			direction = BitcoinTerminalConst.MARKET_LEVEL_DIRECTION_ASK;
		} else {
			direction = BitcoinTerminalConst.MARKET_LEVEL_DIRECTION_BID;
		}
		
		ConnectorMarketStore connectorMarketStore = this.connectorMarketStores.get(connectorClassName);
		
		switch(marketDepthUpdate.getUpdateType()) {
		
			case MarketDepthUpdate.UPDATE_TYPE_ADD_LEVEL:
				this.addMarketLevel(
						connectorMarketStore, 
						marketDepthUpdate.getReference(), 
						direction, 
						marketDepthUpdate.getPrice(), 
						marketDepthUpdate.getVolume());
				
				break;
				
			case MarketDepthUpdate.UPDATE_TYPE_REMOVE_LEVEL:
				this.removeMarketLevel(
						connectorMarketStore, 
						marketDepthUpdate.getReference(), 
						direction, 
						marketDepthUpdate.getPrice()); 
				
				break;
				
			case MarketDepthUpdate.UPDATE_TYPE_UPDATE_LEVEL_VOLUME:
				this.updateMarketLevelVolume(
						connectorMarketStore, 
						marketDepthUpdate.getReference(), 
						direction, 
						marketDepthUpdate.getPrice(), 
						marketDepthUpdate.getVolume());
				
				break;
				
		}
		
	}
	
	private void addMarketLevel(ConnectorMarketStore connectorMarketStore, String reference, int direction, long price, long volume) {
		MarketLevel marketLevel = new MarketLevel(reference, price, volume, direction);
		
		int levelIndex = connectorMarketStore.addMarketLevel(marketLevel);
		
		// update table
		MarketDepthTableController marketDepthTableController = 
				this.marketDepthTableControllerHashedByConnector.get(connectorMarketStore.getConnectorClassName());
		
		MarketDepthLevel marketDepthLevel = new MarketDepthLevel(
				direction, 
				NumberHelper.formatLong(price, 1000000, 6), 
				NumberHelper.formatLong(volume, 100000000, 8));
		
		marketDepthTableController.addMarketDepthLevel(levelIndex, marketDepthLevel);
		
		marketDepthTableController.updateDisplay();
	}
	
	private void removeMarketLevel(ConnectorMarketStore connectorMarketStore, String reference, int direction, long price) {
		int levelIndex = connectorMarketStore.getMarketLevelIndex(reference, direction, price);
		
		connectorMarketStore.removeMarketLevel(reference, direction, price);
		
		// update table
		MarketDepthTableController marketDepthTableController = 
				this.marketDepthTableControllerHashedByConnector.get(connectorMarketStore.getConnectorClassName());
		
		marketDepthTableController.removeMarketDepthLevel(levelIndex, direction);
		
		marketDepthTableController.updateDisplay();
	}
	
	private void updateMarketLevelVolume(ConnectorMarketStore connectorMarketStore, String reference, int direction, long price, long volume) {
		connectorMarketStore.updateMarketLevelVolume(reference, direction, price, volume);
		
		// update table
		MarketDepthTableController marketDepthTableController = 
				this.marketDepthTableControllerHashedByConnector.get(connectorMarketStore.getConnectorClassName());
		
		int levelIndex = connectorMarketStore.getMarketLevelIndex(reference, direction, price);
		
		marketDepthTableController.modifyMarketDepthLevel(
				levelIndex, 
				direction, 
				NumberHelper.formatLong(volume, 100000000, 8), 
				NumberHelper.formatLong(price, 1000000, 6));
		
		marketDepthTableController.updateDisplay();
	}
	
}
